//! 监控和指标收集模块
//! 
//! 这个模块负责应用程序的监控和指标收集，包括：
//! - Prometheus指标收集
//! - 健康检查
//! - 性能监控

use prometheus::{
    Counter, Histogram, Gauge, Registry, IntCounter, IntGauge, HistogramOpts,
    Encoder, TextEncoder,
};
use std::time::Instant;
use axum::{
    extract::State,
    response::Json,
    http::StatusCode,
};
use serde_json::json;

use crate::{
    AppState,
    errors::AppError,
};

/// 应用程序监控指标
#[derive(Clone)]
pub struct Metrics {
    /// HTTP请求总数
    pub http_requests_total: IntCounter,
    /// HTTP请求持续时间
    pub http_request_duration: Histogram,
    /// 活跃连接数
    pub active_connections: IntGauge,
    /// 数据库连接数
    pub database_connections: IntGauge,
    /// 缓存命中数
    pub cache_hits_total: IntCounter,
    /// 缓存未命中数
    pub cache_misses_total: IntCounter,
    /// 错误总数
    pub errors_total: IntCounter,
    /// WebSocket连接数
    pub websocket_connections: IntGauge,
    /// TCP连接数
    pub tcp_connections: IntGauge,
    /// 内存使用量（MB）
    pub memory_usage_mb: Gauge,
    /// CPU使用率
    pub cpu_usage_percent: Gauge,
    /// 指标注册器
    registry: Registry,
}

impl Metrics {
    /// 创建新的监控指标
    pub fn new() -> Result<Self, prometheus::Error> {
        let registry = Registry::new();

        // HTTP请求指标
        let http_requests_total = IntCounter::new(
            "http_requests_total",
            "Total number of HTTP requests"
        )?;
        registry.register(Box::new(http_requests_total.clone()))?;

        let http_request_duration = Histogram::with_opts(HistogramOpts::new(
            "http_request_duration_seconds",
            "HTTP request duration in seconds"
        ).buckets(vec![0.001, 0.01, 0.1, 0.5, 1.0, 2.0, 5.0]))?;
        registry.register(Box::new(http_request_duration.clone()))?;

        // 连接指标
        let active_connections = IntGauge::new(
            "active_connections",
            "Number of active connections"
        )?;
        registry.register(Box::new(active_connections.clone()))?;

        let websocket_connections = IntGauge::new(
            "websocket_connections",
            "Number of WebSocket connections"
        )?;
        registry.register(Box::new(websocket_connections.clone()))?;

        let tcp_connections = IntGauge::new(
            "tcp_connections",
            "Number of TCP connections"
        )?;
        registry.register(Box::new(tcp_connections.clone()))?;

        // 数据库指标
        let database_connections = IntGauge::new(
            "database_connections",
            "Number of database connections"
        )?;
        registry.register(Box::new(database_connections.clone()))?;

        // 缓存指标
        let cache_hits_total = IntCounter::new(
            "cache_hits_total",
            "Total number of cache hits"
        )?;
        registry.register(Box::new(cache_hits_total.clone()))?;

        let cache_misses_total = IntCounter::new(
            "cache_misses_total",
            "Total number of cache misses"
        )?;
        registry.register(Box::new(cache_misses_total.clone()))?;

        // 错误指标
        let errors_total = IntCounter::new(
            "errors_total",
            "Total number of errors"
        )?;
        registry.register(Box::new(errors_total.clone()))?;

        // 系统指标
        let memory_usage_mb = Gauge::new(
            "memory_usage_mb",
            "Memory usage in megabytes"
        )?;
        registry.register(Box::new(memory_usage_mb.clone()))?;

        let cpu_usage_percent = Gauge::new(
            "cpu_usage_percent",
            "CPU usage percentage"
        )?;
        registry.register(Box::new(cpu_usage_percent.clone()))?;

        Ok(Self {
            http_requests_total,
            http_request_duration,
            active_connections,
            database_connections,
            cache_hits_total,
            cache_misses_total,
            errors_total,
            websocket_connections,
            tcp_connections,
            memory_usage_mb,
            cpu_usage_percent,
            registry,
        })
    }

    /// 记录HTTP请求
    pub fn record_http_request(&self, duration: f64) {
        self.http_requests_total.inc();
        self.http_request_duration.observe(duration);
    }

    /// 记录错误
    pub fn record_error(&self) {
        self.errors_total.inc();
    }

    /// 记录缓存命中
    pub fn record_cache_hit(&self) {
        self.cache_hits_total.inc();
    }

    /// 记录缓存未命中
    pub fn record_cache_miss(&self) {
        self.cache_misses_total.inc();
    }

    /// 更新连接指标
    pub fn update_connections(&self, websocket_count: i64, tcp_count: i64) {
        self.websocket_connections.set(websocket_count);
        self.tcp_connections.set(tcp_count);
        self.active_connections.set(websocket_count + tcp_count);
    }

    /// 更新数据库连接指标
    pub fn update_database_connections(&self, total: i64) {
        self.database_connections.set(total);
    }

    /// 更新系统指标
    pub fn update_system_metrics(&self, memory_mb: f64, cpu_percent: f64) {
        self.memory_usage_mb.set(memory_mb);
        self.cpu_usage_percent.set(cpu_percent);
    }

    /// 获取所有指标
    pub fn gather(&self) -> String {
        let metric_families = self.registry.gather();
        let encoder = TextEncoder::new();
        encoder.encode_to_string(&metric_families).unwrap_or_default()
    }
}

/// 启动监控服务
pub async fn start_monitoring(metrics: Metrics) -> tokio::task::JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> {
    tokio::spawn(async move {
        let mut interval = tokio::time::interval(std::time::Duration::from_secs(30));
        
        loop {
            interval.tick().await;
            
            // 更新系统指标
            update_system_metrics(&metrics).await;
            
            tracing::debug!("📊 监控指标已更新");
        }
    })
}

/// 更新系统指标
async fn update_system_metrics(metrics: &Metrics) {
    // 获取内存使用量
    let memory_usage = get_memory_usage().await;
    metrics.memory_usage_mb.set(memory_usage);

    // 获取CPU使用率
    let cpu_usage = get_cpu_usage().await;
    metrics.cpu_usage_percent.set(cpu_usage);
}

/// 获取内存使用量（MB）
async fn get_memory_usage() -> f64 {
    // 简化实现，实际应用中应该使用系统API
    // 这里返回一个模拟值
    128.0
}

/// 获取CPU使用率
async fn get_cpu_usage() -> f64 {
    // 简化实现，实际应用中应该使用系统API
    // 这里返回一个模拟值
    25.0
}

/// Prometheus指标端点处理器
pub async fn metrics_handler(State(state): State<AppState>) -> Result<String, StatusCode> {
    // 更新连接指标
    let websocket_count = state.websocket.get_online_users_count().await as i64;
    let (tcp_total, tcp_active) = (0, 0); // TCP连接统计暂时设为0
    let tcp_count = tcp_active as i64;
    
    state.metrics.update_connections(websocket_count, tcp_count);

    // 更新数据库连接指标
    let (db_total, _db_idle) = state.db.get_pool_info();
    state.metrics.update_database_connections(db_total as i64);

    // 返回指标数据
    Ok(state.metrics.gather())
}

/// 健康检查响应
#[derive(Debug, serde::Serialize)]
pub struct HealthCheckResponse {
    pub status: String,
    pub version: String,
    pub timestamp: chrono::DateTime<chrono::Utc>,
    pub checks: std::collections::HashMap<String, ServiceCheck>,
}

/// 服务检查结果
#[derive(Debug, serde::Serialize)]
pub struct ServiceCheck {
    pub status: String,
    pub response_time_ms: Option<u64>,
    pub error: Option<String>,
    pub details: Option<std::collections::HashMap<String, serde_json::Value>>,
}

/// 健康检查处理器
pub async fn health_check_handler(State(state): State<AppState>) -> Json<HealthCheckResponse> {
    let mut checks = std::collections::HashMap::new();
    let mut overall_status = "healthy";

    // 检查数据库
    let db_start = Instant::now();
    match state.db.health_check().await {
        Ok(_) => {
            let response_time = db_start.elapsed().as_millis() as u64;
            checks.insert("database".to_string(), ServiceCheck {
                status: "healthy".to_string(),
                response_time_ms: Some(response_time),
                error: None,
                details: None,
            });
        }
        Err(e) => {
            overall_status = "unhealthy";
            checks.insert("database".to_string(), ServiceCheck {
                status: "unhealthy".to_string(),
                response_time_ms: None,
                error: Some(e.to_string()),
                details: None,
            });
        }
    }

    // 检查Redis
    let redis_start = Instant::now();
    match state.cache.health_check().await {
        Ok(_) => {
            let response_time = redis_start.elapsed().as_millis() as u64;
            checks.insert("redis".to_string(), ServiceCheck {
                status: "healthy".to_string(),
                response_time_ms: Some(response_time),
                error: None,
                details: None,
            });
        }
        Err(e) => {
            overall_status = "unhealthy";
            checks.insert("redis".to_string(), ServiceCheck {
                status: "unhealthy".to_string(),
                response_time_ms: None,
                error: Some(e.to_string()),
                details: None,
            });
        }
    }

    // 检查连接状态
    let websocket_count = state.websocket.get_online_users_count().await;
    let (tcp_total, tcp_active) = (0, 0); // TCP连接统计暂时设为0
    
    let mut connection_details = std::collections::HashMap::new();
    connection_details.insert("websocket_connections".to_string(), json!(websocket_count));
    connection_details.insert("tcp_total_connections".to_string(), json!(tcp_total));
    connection_details.insert("tcp_active_connections".to_string(), json!(tcp_active));

    checks.insert("connections".to_string(), ServiceCheck {
        status: if websocket_count > 1000 || tcp_total > 1000 { "warning" } else { "healthy" }.to_string(),
        response_time_ms: None,
        error: None,
        details: Some(connection_details),
    });

    // 检查内存使用
    let memory_usage = get_memory_usage().await;
    let mut memory_details = std::collections::HashMap::new();
    memory_details.insert("usage_mb".to_string(), json!(memory_usage));

    checks.insert("memory".to_string(), ServiceCheck {
        status: if memory_usage > 1000.0 { "warning" } else { "healthy" }.to_string(),
        response_time_ms: None,
        error: None,
        details: Some(memory_details),
    });

    Json(HealthCheckResponse {
        status: overall_status.to_string(),
        version: env!("CARGO_PKG_VERSION").to_string(),
        timestamp: chrono::Utc::now(),
        checks,
    })
}

/// 监控中间件
pub async fn metrics_middleware(
    State(metrics): State<Metrics>,
    request: axum::extract::Request,
    next: axum::middleware::Next,
) -> axum::response::Response {
    let start = Instant::now();
    
    // 记录请求开始
    metrics.http_requests_total.inc();
    
    let response = next.run(request).await;
    
    // 记录请求完成
    let duration = start.elapsed();
    metrics.http_request_duration.observe(duration.as_secs_f64());
    
    // 记录错误
    if response.status().is_client_error() || response.status().is_server_error() {
        metrics.record_error();
    }
    
    response
}

/// 系统信息结构
#[derive(Debug, serde::Serialize)]
pub struct SystemInfo {
    pub version: String,
    pub uptime_seconds: u64,
    pub memory_usage_mb: f64,
    pub cpu_usage_percent: f64,
    pub active_connections: usize,
    pub database_connections: (usize, usize),
    pub cache_connections: (usize, usize),
}

/// 系统信息处理器
pub async fn system_info_handler(State(state): State<AppState>) -> Json<SystemInfo> {
    let websocket_count = state.websocket.get_online_users_count().await;
    let (tcp_total, tcp_active) = (0, 0); // TCP连接统计暂时设为0
    let db_info = state.db.get_pool_info();
    let cache_info = state.cache.get_pool_info();
    
    Json(SystemInfo {
        version: env!("CARGO_PKG_VERSION").to_string(),
        uptime_seconds: 0, // 实际应用中应该记录启动时间
        memory_usage_mb: get_memory_usage().await,
        cpu_usage_percent: get_cpu_usage().await,
        active_connections: websocket_count + tcp_active,
        database_connections: db_info,
        cache_connections: cache_info,
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_metrics_creation() {
        let metrics = Metrics::new().unwrap();
        
        // 测试指标记录
        metrics.record_http_request(0.1);
        metrics.record_error();
        metrics.record_cache_hit();
        metrics.record_cache_miss();
        metrics.update_connections(10, 5);
        metrics.update_database_connections(20);
        metrics.update_system_metrics(128.0, 25.0);
        
        // 验证指标数据不为空
        let metrics_data = metrics.gather();
        assert!(!metrics_data.is_empty());
        assert!(metrics_data.contains("http_requests_total"));
        assert!(metrics_data.contains("active_connections"));
    }

    #[tokio::test]
    async fn test_health_check() {
        // 这个测试需要实际的AppState，为了简化，我们跳过具体实现
        assert!(true);
    }
}
